package com.wa.aspect;

import com.wa.annotation.AllchipsLog;
import com.wa.annotation.AllchipsLogModel;
import com.wa.api.ILogMessageApi;
import com.wa.dto.OperatorInfoDto;
import com.wa.service.IAllchipsLogHandleService;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * 日志切面类
 *
 * @Author Dawn
 * @Date 2021/10/15 10:59
 */
@Slf4j
@Aspect
@Builder
@Component
@ConditionalOnProperty(prefix = "spring.allchips.log", name = "enable", havingValue = "true")
public class AllchipsLogAdvice {
    @Resource
    private ILogMessageApi logMessageApi;
    @Resource
    private IAllchipsLogHandleService allchipsLogHandleService;

    @Pointcut("@annotation(com.allchips.beans.log.annotation.AllchipsLog)")
    public void point() {
    }

    @Around("point() && @annotation(allchipsLogAnn)")
    public Object aroundBuff(ProceedingJoinPoint joinPoint, AllchipsLog allchipsLogAnn) throws Throwable {
        //继续下一个建议或目标方法调用
        Object result = joinPoint.proceed();
        // 存储日志
        this.saveLog(joinPoint, allchipsLogAnn);

        return result;
    }

    /**
     * 存储日志
     *
     * @Author Dawn
     * @Date 2021/10/18 10:07
     */
    private void saveLog(ProceedingJoinPoint joinPoint, AllchipsLog allchipsLogAnn) {
        try {
            //此连接点处的参数
            Object[] params = joinPoint.getArgs();
            if (params.length == 0) {
                return;
            }
            //连接点的签名。
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            //声明此成员的类、接口或方面
            Class clazz = methodSignature.getDeclaringType();
            Method method = clazz.getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes());
            // 方法参数的注解
            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
            // 需要存储日志的对象
            Object dataObject = null;
            for (int i = 0; i < parameterAnnotations.length; i++) {
                Annotation[] ann = parameterAnnotations[i];
                if (params[i] == null || ann.length == 0) {
                    continue;
                }
                for (Annotation annotation : ann) {
                    //获取到第一个AllchipsLogModel注解后返回
                    if (annotation.annotationType().equals(AllchipsLogModel.class)) {
                        dataObject = params[i];
                        break;
                    }
                }
            }
            // 获取操作者信息
            OperatorInfoDto operatorInfoDto = allchipsLogHandleService.getOperatorInfo();
            // 存储日志处理
            allchipsLogHandleService.saveLog(dataObject, operatorInfoDto, allchipsLogAnn.module(), allchipsLogAnn.type());
        } catch (Exception e) {
            log.error("******************日志生成失败，异常信息：", e);
        }
    }

}
